package com.coderside.fragment.socket;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author root
 */
public class Main implements Runnable {

	//服务器channel对象，负责接受用户的连接
	private ServerSocketChannel server;

	//Selector对象，负责监控所有的连接到服务器的网络事件的发生
	private Selector selector;

	//总的活动连接数
	private int activeSockets;

	//服务器channel绑定的端口
	private int port;

	public Main() throws IOException {
		activeSockets = 0;

		port = 9999;

		selector = Selector.open();//初始化 Selector对象

		ServerSocket socket = server.socket();//获取服务器channel对应的Serverocket对象

		socket.bind(new InetSocketAddress(port));//把socket帮定到监听端口9999上

		server.configureBlocking(false);//将服务器channel设置为非阻塞模式

		server.register(selector, SelectionKey.OP_ACCEPT);//将服务器Channel注册到Selector 对象,并指出服务器Channel所感兴趣的时间

	}

	public void run() {

		while (true) {
			try {
				/*
				 *应用Select机制循环监控是否有用户感兴趣的网络事件发生，当
				 * 没有网络事件发生，此方法处于堵塞状态，
				 * 知道有新的网络时间发生为止
				 */
				selector.select();

			} catch (IOException ex) {
				Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
				continue;
			}

			//得到活动的网络连接选择建的集合

			Set<SelectionKey> keys = selector.selectedKeys();

			activeSockets = keys.size();

			//如果活动连接数为0，则继续进行循环操作
			if (activeSockets == 0) {
				continue;
			}

			//遍历整个选择键集合
			for (SelectionKey key : keys) {
				//如果关键字状态是为可接受，则接受连接，注册通道，以接受更多的事件，进行相关的服务器程序处理

				if (key.isAcceptable()) {

					//执行相关代码
					continue;
				}

				//如果关键字状态为可写，则也说明Channel是一个客户端的连接通道,进行相关的向客户端写述据的操作

				if (key.isWritable()) {
					//执行相关代码

					continue;
				}
			}

		}

	}

	/*
	 *处理服务器事件的操作
	 */
	public void doServerSocketEvent(SelectionKey key) {
		SocketChannel client = null;
		try {
			client = null;
			ServerSocketChannel server = (ServerSocketChannel) key.channel();
			client = server.accept();

			if (client == null) {
				return;
			}

			client.configureBlocking(false);//将客户端Channel设置为非堵塞型

			client.register(selector, SelectionKey.OP_READ | SelectionKey.OP_READ);

		} catch (IOException ex) {
			try {
				client.close();
				Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
			} catch (IOException ex1) {
				Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex1);
			}
		}
	}

	/*
	 *进行向客户端写述据的操作
	 * ＠param key 客户端选择键对象
	 */
	private void doClientWriteEvent(SelectionKey key) {

	}

	/*
	 *进行读取客户端述据操作
	 */
	private void doClientReadEvent(SelectionKey key) {

	}

}